import type { UseFetchOptions } from 'nuxt/app'
import type { FetchError } from 'ofetch'

/**
 * API 响应状态码枚举
 */
export enum ApiStatusCode {
  SUCCESS = 200,
  TOKEN_EXPIRED = 210311001, // Token 过期
  UNAUTHORIZED = 401, // 未授权
  FORBIDDEN = 403, // 禁止访问
  NOT_FOUND = 404, // 资源不存在
  INTERNAL_SERVER_ERROR = 210311099, // 服务器内部错误
  BAD_REQUEST = 400, // 请求参数错误
  NETWORK_ERROR = 0 // 网络错误
}

/**
 * 标准 API 响应接口
 */
export interface ApiResponse<T = any> {
  status: number
  data: T
  msg: string
  success: boolean
  timestamp?: number
}

/**
 * URL 类型定义
 */
export type ApiUrl = string | Request | Ref<string | Request> | (() => string | Request)

/**
 * HTTP 方法类型
 */
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'

/**
 * 基础请求选项
 */
export type BaseHttpOptions<T> = UseFetchOptions<ApiResponse<T>>

/**
 * 扩展请求配置接口
 */
export interface RequestConfig<T = any> extends BaseHttpOptions<T> {
  /** 忽略错误拦截，直接返回原始响应数据 */
  ignoreCatch?: boolean
  /** 是否需要手动刷新数据 */
  needRefresh?: boolean
  /** 忽略全局错误提示 */
  ignoreGlobalErrorMessage?: boolean
  /** 请求超时时间（毫秒） */
  timeout?: number
  /** 是否显示加载状态 */
  showLoading?: boolean
  /** 自定义错误处理函数 */
  onError?: (error: FetchError | Error) => void
  /** 请求重试次数 */
  retryCount?: number
  /** 重试延迟时间（毫秒） */
  retryDelay?: number
}

/**
 * 错误处理配置
 */
interface ErrorHandlerConfig {
  message: string
  showToast: boolean
  logError: boolean
}

/**
 * 请求拦截器类型
 */
type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>

/**
 * 响应拦截器类型
 */
type ResponseInterceptor<T> = (response: ApiResponse<T>) => ApiResponse<T> | Promise<ApiResponse<T>>

/**
 * 请求管理器类
 */
class RequestManager {
  private requestInterceptors: RequestInterceptor[] = []
  private responseInterceptors: ResponseInterceptor<any>[] = []
  private loadingCount = 0

  /**
   * 添加请求拦截器
   * @param interceptor 拦截器函数
   */
  addRequestInterceptor(interceptor: RequestInterceptor): void {
    this.requestInterceptors.push(interceptor)
  }

  /**
   * 添加响应拦截器
   * @param interceptor 拦截器函数
   */
  addResponseInterceptor<T>(interceptor: ResponseInterceptor<T>): void {
    this.responseInterceptors.push(interceptor)
  }

  /**
   * 执行请求拦截器
   * @param config 请求配置
   */
  async executeRequestInterceptors(config: RequestConfig): Promise<RequestConfig> {
    let processedConfig = config
    for (const interceptor of this.requestInterceptors) {
      processedConfig = await interceptor(processedConfig)
    }
    return processedConfig
  }

  /**
   * 执行响应拦截器
   * @param response 响应数据
   */
  async executeResponseInterceptors<T>(response: ApiResponse<T>): Promise<ApiResponse<T>> {
    let processedResponse = response
    for (const interceptor of this.responseInterceptors) {
      processedResponse = await interceptor(processedResponse)
    }
    return processedResponse
  }

  /**
   * 显示加载状态
   */
  showLoading(): void {
    this.loadingCount++
    // 这里可以集成全局加载状态管理
    // const systemStore = useSystemStore()
    // systemStore.setLoading(true)
  }

  /**
   * 隐藏加载状态
   */
  hideLoading(): void {
    this.loadingCount--
    if (this.loadingCount <= 0) {
      this.loadingCount = 0
      // const systemStore = useSystemStore()
      // systemStore.setLoading(false)
    }
  }
}

// 创建全局请求管理器实例
const requestManager = new RequestManager()

/**
 * 处理错误信息
 * @param error 错误对象
 * @param config 错误处理配置
 */
function handleError(error: FetchError | Error | string, config: ErrorHandlerConfig): void {
  const { message, showToast, logError } = config

  if (logError) {
    console.error('[API Error]:', error)
  }

  if (showToast) {
    // 这里可以集成全局提示组件
    // const { $toast } = useNuxtApp()
    // $toast.error(message)
    console.error(message)
  }
}

/**
 * 获取错误消息
 * @param error 错误对象
 * @param defaultMessage 默认错误消息
 */
function getErrorMessage(error: FetchError | Error | string, defaultMessage = '请求失败'): string {
  if (typeof error === 'string') {
    return error
  }

  if (error instanceof Error) {
    return error.message || defaultMessage
  }

  return defaultMessage
}

/**
 * 延迟函数
 * @param ms 延迟毫秒数
 */
function delay(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms))
}

/**
 * 核心请求函数
 * @param url 请求地址
 * @param params 请求参数
 * @param options 请求配置
 */
async function request<T>(
  url: ApiUrl,
  params?: any,
  options: RequestConfig<T> = {}
): Promise<ApiResponse<T> | T> {
  // 执行请求拦截器
  const processedOptions = await requestManager.executeRequestInterceptors(options)

  const {
    ignoreCatch = false,
    ignoreGlobalErrorMessage = false,
    needRefresh = false,
    timeout = 10000,
    showLoading = false,
    onError,
    retryCount = 0,
    retryDelay = 1000,
    ...fetchOptions
  } = processedOptions

  const headers = useRequestHeaders(['cookie'])
  const method = (fetchOptions.method || 'GET') as HttpMethod
  const runtimeConfig = useRuntimeConfig()
  const baseURL: string = runtimeConfig.public.baseUrl as string;

  // 显示加载状态
  if (showLoading) {
    requestManager.showLoading()
  }

  // 构建请求配置
  const requestConfig: UseFetchOptions<ApiResponse<T>> = {
    baseURL,
    headers: {
      'Content-Type': 'application/json',
      ...headers,
      ...fetchOptions.headers
    },
    timeout,
    server: true, // 强制服务端渲染，确保数据在服务端获取
    ...fetchOptions
  }

  // 根据请求方法设置参数
  if (method === 'GET') {
    requestConfig.params = params
  } else {
    requestConfig.body = params ? JSON.stringify(params) : undefined
  }

  let lastError: FetchError | Error | null = null
  let attempt = 0

  // 重试逻辑
  while (attempt <= retryCount) {
    try {
      const { data, error, refresh } = await useFetch<ApiResponse<T>>(url, requestConfig)

      // 隐藏加载状态
      if (showLoading) {
        requestManager.hideLoading()
      }

      // 处理网络错误
      if (error.value) {
        throw error.value
      }

      // 处理响应数据为空的情况
      if (!data.value) {
        throw new Error('响应数据为空')
      }

      const responseData = data.value

      // 执行响应拦截器
      const processedResponse = await requestManager.executeResponseInterceptors(responseData)

      const { status, data: result, msg } = processedResponse

      // 处理刷新逻辑
      if (needRefresh && refresh) {
        refresh()
      }

      // 请求成功
      if (status === ApiStatusCode.SUCCESS || !status) {
        return ignoreCatch ? processedResponse : result
      }

      // 处理业务错误
      if (!ignoreCatch) {
        const errorMessage = msg || '请求失败'

        if (!ignoreGlobalErrorMessage) {
          handleError(errorMessage, {
            message: errorMessage,
            showToast: true,
            logError: true
          })
        }

        if (onError) {
          onError(new Error(errorMessage))
        }

        throw new Error(errorMessage)
      }

      return processedResponse

    } catch (error) {
      lastError = error as FetchError | Error
      attempt++

      // 如果还有重试次数，等待后重试
      if (attempt <= retryCount) {
        await delay(retryDelay)
        continue
      }

      // 隐藏加载状态
      if (showLoading) {
        requestManager.hideLoading()
      }

      // 处理最终错误
      const errorMessage = getErrorMessage(lastError, '网络请求失败，请稍后重试')

      if (!ignoreGlobalErrorMessage) {
        handleError(lastError, {
          message: errorMessage,
          showToast: true,
          logError: true
        })
      }

      if (onError) {
        onError(lastError)
      }

      throw lastError
    }
  }

  throw lastError || new Error('请求失败')
}

/**
 * HTTP 请求方法集合
 */
export const useDefaultRequest = {
  /**
   * GET 请求
   * @param url 请求地址
   * @param params 查询参数
   * @param options 请求配置
   */
  get: <T = any>(url: ApiUrl, params?: any, options?: RequestConfig<T>) => {
    return request<T>(url, params, { method: 'GET', ...options })
  },

  /**
   * POST 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param options 请求配置
   */
  post: <T = any>(url: ApiUrl, data?: any, options?: RequestConfig<T>) => {
    return request<T>(url, data, { method: 'POST', ...options })
  },

  /**
   * PUT 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param options 请求配置
   */
  put: <T = any>(url: ApiUrl, data?: any, options?: RequestConfig<T>) => {
    return request<T>(url, data, { method: 'PUT', ...options })
  },

  /**
   * DELETE 请求
   * @param url 请求地址
   * @param params 查询参数
   * @param options 请求配置
   */
  delete: <T = any>(url: ApiUrl, params?: any, options?: RequestConfig<T>) => {
    return request<T>(url, params, { method: 'DELETE', ...options })
  },

  /**
   * PATCH 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param options 请求配置
   */
  patch: <T = any>(url: ApiUrl, data?: any, options?: RequestConfig<T>) => {
    return request<T>(url, data, { method: 'PATCH', ...options })
  },

  /**
   * 添加请求拦截器
   * @param interceptor 拦截器函数
   */
  addRequestInterceptor: (interceptor: RequestInterceptor) => {
    requestManager.addRequestInterceptor(interceptor)
  },

  /**
   * 添加响应拦截器
   * @param interceptor 拦截器函数
   */
  addResponseInterceptor: <T>(interceptor: ResponseInterceptor<T>) => {
    requestManager.addResponseInterceptor(interceptor)
  }
}

/**
 * 默认导出，兼容旧版本使用方式
 */
export default useDefaultRequest

/**
 * 使用示例：
 * 
 * // 基础使用
 * const result = await useDefaultRequest.get<UserInfo>('/user/info')
 * 
 * // 带参数的 POST 请求
 * const response = await useDefaultRequest.post<CreateResult>('/user/create', {
 *   name: 'John',
 *   email: 'john@example.com'
 * })
 * 
 * // 带配置的请求
 * const data = await useDefaultRequest.get<ListData>('/news/list', 
 *   { page: 1, size: 20 }, 
 *   { 
 *     showLoading: true,
 *     retryCount: 2,
 *     timeout: 5000
 *   }
 * )
 * 
 * // 添加请求拦截器
 * useDefaultRequest.addRequestInterceptor((config) => {
 *   // 添加认证 token
 *   const token = useCookie('auth-token')
 *   if (token.value) {
 *     config.headers = {
 *       ...config.headers,
 *       Authorization: `Bearer ${token.value}`
 *     }
 *   }
 *   return config
 * })
 * 
 * // 添加响应拦截器
 * useDefaultRequest.addResponseInterceptor((response) => {
 *   // 处理特殊状态码
 *   if (response.status === ApiStatusCode.TOKEN_EXPIRED) {
 *     // 跳转到登录页
 *     navigateTo('/login')
 *   }
 *   return response
 * })
 */